package zack.middleware.hystrix.valve.impl;

import com.alibaba.fastjson.JSON;
import com.netflix.hystrix.*;
import org.aspectj.lang.ProceedingJoinPoint;
import zack.middleware.hystrix.annotation.DoHystrix;
import zack.middleware.hystrix.valve.IValveService;

import java.lang.reflect.Method;

public class HystrixValveImpl extends HystrixCommand<Object> implements IValveService {


    private ProceedingJoinPoint jp;
    private Method method;
    private DoHystrix doHystrix;

    public HystrixValveImpl(DoHystrix doHystrix) {


        /*********************************************************************************************
         * 置HystrixCommand的属性
         * GroupKey：            为 Hystrix 命令指定一个「组」，用于对命令进行逻辑分组管理。
         * 具体含义："GovernGroup" 是组的名称，相同组的命令会被归为一类，方便在 Hystrix 监控面板中聚合展示统计信息（如失败率、超时率），
         * 也用于资源隔离的默认分组依据（若未单独指定线程池，会默认按组分配线程池）。
         * CommandKey：         为当前 Hystrix 命令指定一个唯一标识，用于区分不同的命令。
         * 具体含义："GovernKey" 是命令的唯一名称，即使多个命令属于同一组（GovernGroup），也可以通过 CommandKey 单独标识。
         * 在监控、日志和熔断规则配置中，CommandKey 是定位具体命令的关键。
         * ThreadPoolKey：       为命令指定所属的线程池，实现「线程隔离」（Hystrix 核心特性之一）。
         * 具体含义："GovernThreadPool" 是线程池的名称，所有使用该标识的命令会共享同一个线程池。
         * 线程隔离的目的是避免单个命令的故障（如耗时过长、异常）耗尽整个应用的线程资源，例如：若该线程池核心线程数为 10，则同时最多只能执行 10 个该命令的任务，超过则进入队列或被拒绝。
         * CommandProperties：   配置命令的核心行为规则（如隔离策略、超时时间、熔断阈值等）。
         * 具体含义：这里仅配置了「隔离策略」：
         * ExecutionIsolationStrategy.THREAD 表示使用「线程隔离」模式，即 Hystrix 会在独立的线程（属于 GovernThreadPool 线程池）中执行命令的业务逻辑（run() 方法），避免业务逻辑阻塞主线程。
         * （Hystrix 还有另一种隔离策略 SEMAPHORE，通过信号量控制并发，不创建新线程，适用于轻量场景）。
         * ThreadPoolProperties：关于线程池的配置，包括线程池大小，排队队列的大小等
         *********************************************************************************************/
        super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("GovernGroup"))
                .andCommandKey(HystrixCommandKey.Factory.asKey("GovernKey"))
                .andThreadPoolKey(HystrixThreadPoolKey.Factory.asKey("GovernThreadPool"))
                .andCommandPropertiesDefaults(HystrixCommandProperties.Setter()
                        .withExecutionIsolationStrategy(HystrixCommandProperties.ExecutionIsolationStrategy.THREAD)
                        .withExecutionTimeoutInMilliseconds(doHystrix.timeout())
                )
                .andThreadPoolPropertiesDefaults(HystrixThreadPoolProperties.Setter().withCoreSize(10))
        );
        this.doHystrix = doHystrix;

    }

    /**
     * 放在hystrix定义的线程池中运行
     * @return
     * @throws Exception
     */
    @Override
    protected Object run() throws Exception {
        try{
            //执行被拦截的原方法
            return jp.proceed();
        }catch (Throwable e){
            return null;
        }
    }

    @Override
    public Object access(ProceedingJoinPoint jp, Method method, Object[] args) throws Throwable {

        this.jp = jp;
        this.method = method;


      return this.execute();
    }

    /**
     * 当线程池中运行的run方法出现异常时，会自动调用该方法，返回定义的熔断信息
     * @return
     */
    @Override
    protected Object getFallback() {
        return JSON.parseObject(doHystrix.returnJson(),method.getReturnType());
    }
}
